<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body,
        html {
            width: 100%;
            height: 100%;
            background-color: #000;
        }
    </style>
</head>

<body>
    <canvas id="cvs"></canvas>
    <script>
        var cvs = document.getElementById("cvs");
        cvs.width = document.body.clientWidth;
        cvs.height = document.body.clientHeight;
        var context = cvs.getContext('2d');

        //重写数组的方法
        Array.prototype.forEach = function (callback) {
            for (var i = 0; i < this.length; i++) {
                callback.call(this[i]);
            }
        }
        // 定义圆点类
        function Point(x, y, z, radius) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.radius = radius;
            this.light = "rgba(100,100,255,.3)";
            this.side = "rgba(0,175,255,0.2)";
            this.center = "rgba(0,100,255,.5)"
        }
        Point.prototype.draw = function (context,offset) {
            context.strokeStyle = 'red';
            context.fillStyle = this.side;
            context.beginPath();
            context.arc(this.x + offset, this.y + offset, this.radius * 1.5, 0, Math.PI * 2);
            context.fill();
            context.fillStyle = this.light;
            context.beginPath();
            context.arc(this.x + offset, this.y + offset, this.radius, 0, Math.PI * 2);
            context.fill();
            context.fillStyle = this.center;
            context.beginPath();
            context.arc(this.x + offset, this.y + offset, this.radius * 0.5, 0, Math.PI * 2);
            context.fill();
        }

        // test
        // var p1 = new Point(400,200,0,10);
        // p1.draw(context);

        // 定义球体类
        function Cube() {

        }
        Cube.prototype.init = function () {
            this.points = [];
            for (var i = 0; i < 24; i++) {
                for (var e = 0; e < 24; e++) {
                    // 圆点的x
                    var x = Math.cos(i * Math.PI * 2 / 24) * Math.sin(e * Math.PI * 2 / 24) * 300;
                    // 圆点的y
                    var y = Math.cos(e * Math.PI * 2 / 24) * 300;
                    var z = 0;
                    if ((e / 24 > 0.5) || (i / 24) > 0.5) {
                        z = 0 - Math.sqrt(Math.pow(300, 2) - Math.pow(x, 2) - Math.pow(y, 2));
                    } else {
                        z = Math.sqrt(Math.pow(300, 2) - Math.pow(x, 2) - Math.pow(y, 2));
                    }

                    var r = 2 + 2 * Math.sqrt(Math.pow(300 + 20 - z, 2) + Math.pow(y, 2)) / (20 + 300);
                    // console.log(x, y, z, r);
                    var p = new Point(x, y, z, r);
                    this.points.push(p);
                }
            }
        }
        Cube.prototype.draw = function (context) {
            for(var i = 0; i < this.points.length; i++){
                this.points[i].draw(context,350);
            }
        }
        Cube.prototype.transform = function(ax,ay){
            context.clearRect(0, 0, cvs.width, cvs.height);
            rotateX(this.points,ax);
            rotateY(this.points,ay);
            this.draw(context); 
        }


        function rotateX(points, angleY) {
                var cos = Math.cos(angleY)
                var sin = Math.sin(angleY)
                points.forEach(function () {
                    var y1 = this.y * cos - this.z * sin
                    var z1 = this.y * sin + this.z * cos
                    this.y = y1
                    this.z = z1
                })
            }

            function rotateY(points, angleY) {
                var cos = Math.cos(angleY)
                var sin = Math.sin(angleY)
                points.forEach(function () {
                    var z1 = this.z * cos - this.x * sin
                    var x1 = this.z * sin + this.x * cos
                    this.z = z1
                    this.x = x1
                })
            }

        var cube = new Cube();
        cube.init();
        cube.draw(context);

        var x_ = 1000;
        var y_ = 1000;
        document.onmousemove = function(e){
            var rx = e.pageX
            var ry = e.pageY
            var deltaX = rx - x_
            var deltaY = ry - y_
            cube.transform(deltaY / 8000 * Math.PI, -deltaX / 8000 * Math.PI)
            x_ = rx
            y_ = ry
        }
    </script>
</body>

</html>